
//******************************************************************************/

#include "esp32_oled.h"
#include "stdlib.h"

#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "sys/unistd.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

static spi_device_handle_t spi;

static spi_bus_config_t buscfg={
		.miso_io_num=-1,//MISO信号线，可复用为QSPI的D0
		.mosi_io_num=PIN_OLED_DIN,//MOSI信号线，可复用为QSPI的D1
		.sclk_io_num=PIN_OLED_CLK,//SCLK信号线
		.quadwp_io_num=-1,//WP信号线，专用于QSPI的D2
		.quadhd_io_num=-1,//HD信号线，专用于QSPI的D3
		.max_transfer_sz=4094,//最大传输数据大小，单位字节，默认为4094
	    //.intr_flags,//中断指示位
};

 void oled_spi_init(void)
 {
  	esp_err_t ret;

  	esp_rom_gpio_pad_select_gpio(PIN_OLED_CS);                // 选择一个GPIO
  	gpio_set_direction(PIN_OLED_CS, GPIO_MODE_OUTPUT);// 把这个GPIO作为输出

  	esp_rom_gpio_pad_select_gpio(PIN_OLED_DC);                // 选择一个GPIO
  	gpio_set_direction(PIN_OLED_DC, GPIO_MODE_OUTPUT);// 把这个GPIO作为输出

  	esp_rom_gpio_pad_select_gpio(PIN_OLED_RES);                // 选择一个GPIO
  	gpio_set_direction(PIN_OLED_RES, GPIO_MODE_OUTPUT);// 把这个GPIO作为输出

  	//对于ESP32 超过26Mhz会报错，C系列、S系列未知
  	spi_device_interface_config_t devcfg={
  	.clock_speed_hz =SPI_MASTER_FREQ_26M,      // Clock out at 26 MHz,
  	.mode = 0,                                  // SPI mode 0
  	.spics_io_num = -1,
    .queue_size = 6,                            // 传输队列大小，决定了等待传输数据的数量
  	 };

  	 //Initialize the SPI bus
  	  ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
//  	    ESP_ERROR_CHECK(ret);
  	  ret = spi_bus_add_device(SPI2_HOST, &devcfg, &spi);
//  	    ESP_ERROR_CHECK(ret);
  	}
uint8_t u8x8_byte_hard_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
    /* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
	spi_transaction_t spi_trans;
	esp_err_t ret;
    static uint8_t buf[128];
    static uint8_t buf_idx;

	printf("msg:%d,arg_int:%d\r\n",msg,arg_int);
    switch(msg){
	 case U8X8_MSG_BYTE_SEND: /*通过SPI发送arg_int个字节数据*/
	 {
		 memset(&spi_trans, 0, sizeof(spi_trans));       //Zero out the transaction
		 spi_trans.length=arg_int*8;                 //Len is in bytes, transaction length is in bits.
		 spi_trans.tx_buffer=arg_ptr;               //Data
		 spi_trans.user=(void*)1;                //D/C needs to be set to 1
		 ret=spi_device_polling_transmit(spi, &spi_trans);  //Transmit!
		 assert(ret==ESP_OK);
	 }
		break;
	case U8X8_MSG_BYTE_INIT: /*初始化函数*/
//    	oled_spi_init();
		break;
	case U8X8_MSG_BYTE_SET_DC:
		arg_int==1?OLED_DC_Set():OLED_DC_Clr();
//		esp_rom_delay_us(1);
		break;
	case U8X8_MSG_BYTE_START_TRANSFER:
		OLED_CS_Clr();
//		esp_rom_delay_us(1);
		break;
	case U8X8_MSG_BYTE_END_TRANSFER:
		OLED_CS_Set();
//		esp_rom_delay_us(1);
		break;
	default:
		return 0;
	}
    return 1;
}



uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
//采用硬件spi，部分分支可以忽略不写
    switch (msg)
    {
    //Initialize SPI peripheral
    case U8X8_MSG_GPIO_AND_DELAY_INIT:
        break;
  	//Function which implements a delay, arg_int contains the amount of ms
  	case U8X8_MSG_DELAY_MILLI:
//  		vTaskDelay(pdMS_TO_TICKS(arg_int));
        break;
  	//Function which delays 10us
      case U8X8_MSG_DELAY_10MICRO:
//    	  esp_rom_delay_us(10);
    	  break;
      // Function to define the logic level of the CS line
  	case U8X8_MSG_GPIO_CS:
//  		arg_int==1?OLED_CS_Set():OLED_CS_Clr();
  	  break;
  	//Function to define the logic level of the Data/ Command line
  	case U8X8_MSG_GPIO_DC:
//  		arg_int==1?OLED_DC_Set():OLED_DC_Clr();
  	  break;
  	//Function to define the logic level of the RESET line
  	case U8X8_MSG_GPIO_RESET:
  	  break;
  	default:
  	  return 0; //A message was received which is not implemented, return 0 to indicate an error
    }
    return 1;
}



void u8g2Init(u8g2_t *u8g2)
{
	u8g2_Setup_ssd1306_128x64_noname_f(u8g2, U8G2_R0, u8x8_byte_hard_spi, u8x8_gpio_and_delay);
	u8g2_InitDisplay(u8g2);
	u8g2_SetPowerSave(u8g2, 0);
	u8g2_ClearBuffer(u8g2);
}




















